home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / dev / devSyslog.c < prev    next >
C/C++ Source or Header  |  1990-10-16  |  14KB  |  596 lines

  1. /* 
  2.  * devSyslog.c --
  3.  *
  4.  *    Device driver for processing internal kernel writes to the console.
  5.  *            
  6.  * Copyright 1986 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/kernel/dev/RCS/devSyslog.c,v 9.7 90/10/16 11:19:49 kupfer Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14.  
  15. #include <sprite.h>
  16. #include <dev.h>
  17. #include <fs.h>
  18. #include <fsio.h>
  19. #include <fsioDevice.h>
  20. #include <sys.h>
  21. #include <machMon.h>
  22. #include <sig.h>
  23. #include <stdlib.h>
  24. #include <sync.h>
  25. #include <sched.h>
  26. #include <proc.h>
  27. #include <timer.h>
  28. #include <dbg.h>
  29. #include <list.h>
  30. #include <bstring.h>
  31.  
  32. /*
  33.  * Definition of mutual exclusion variable.
  34.  */
  35. static Sync_Semaphore    syslogMutex = Sync_SemInitStatic("Dev:syslogMutex");
  36. /*
  37.  * Monitored circular buffer of data written out by the kernel.
  38.  */
  39. #define    SYSLOG_BUF_SIZE    8192
  40. static    char    syslogBuffer[SYSLOG_BUF_SIZE];
  41. static    int    firstIndex = -1;
  42. static    int    lastIndex = -1;
  43.  
  44. static    Boolean syslogEnable = TRUE;
  45. static    Boolean    openForReading = FALSE;    /* TRUE if the device is open for
  46.                      * reading.  Only one process can
  47.                      * be reading syslog at a time. */
  48. static    Fs_NotifyToken notifyToken;    /* Used for Fs call-back to notify
  49.                      * waiting processes that the syslog
  50.                      * device is ready.*/
  51. static    Boolean       overflow = FALSE;
  52.  
  53.  
  54. /*
  55.  *----------------------------------------------------------------------
  56.  *
  57.  * Dev_SyslogOpen --
  58.  *
  59.  *    Open the system log device.
  60.  *
  61.  * Results:
  62.  *    SUCCESS        - the device was opened.
  63.  *    FAILURE        - some other reader is already reading the syslog.
  64.  *
  65.  * Side effects:
  66.  *    The system log is "opened" and static variables are initialized.
  67.  *
  68.  *----------------------------------------------------------------------
  69.  */
  70. /*ARGSUSED*/
  71. ReturnStatus
  72. Dev_SyslogOpen(devicePtr, useFlags, token, flagsPtr)
  73.     Fs_Device *devicePtr;    /* Specifies type and unit number. */
  74.     int useFlags;        /* Flags from the stream.  We only allow
  75.                  * a single reader at one time. */
  76.     Fs_NotifyToken token;    /* Used for Fs call-back to notify waiting
  77.                  * processes that the syslog device is ready.*/
  78.     int *flagsPtr;            /* OUT: Device IO flags */
  79. {
  80.     MASTER_LOCK(&syslogMutex);
  81.     Sync_SemRegister(&syslogMutex);
  82.     if (useFlags & FS_READ) {
  83.     if (openForReading) {
  84.         MASTER_UNLOCK(&syslogMutex);
  85.         return(FAILURE);
  86.     }
  87.     openForReading = TRUE;
  88.     }
  89.     notifyToken = token;
  90.     MASTER_UNLOCK(&syslogMutex);
  91.     return(SUCCESS);
  92. }
  93.  
  94. /*
  95.  *----------------------------------------------------------------------
  96.  *
  97.  * Dev_SyslogReopen --
  98.  *
  99.  *    Reopen the system log device.  This uses Dev_SyslogOpen to
  100.  *    do all the work.
  101.  *
  102.  * Results:
  103.  *    SUCCESS        - the device was opened.
  104.  *    FAILURE        - some other reader is already reading the syslog.
  105.  *
  106.  * Side effects:
  107.  *    See Dev_SyslogOpen.
  108.  *
  109.  *----------------------------------------------------------------------
  110.  */
  111. /*ARGSUSED*/
  112. ReturnStatus
  113. Dev_SyslogReopen(devicePtr, refs, writers, token, flagsPtr)
  114.     Fs_Device *devicePtr;    /* Specifies type and unit number. */
  115.     int refs;            /* Number of existing opens */
  116.     int writers;        /* Number of existing writers */
  117.     Fs_NotifyToken token;    /* Used for Fs call-back to notify waiting
  118.                  * processes that the console device is ready.*/
  119.     int *flagsPtr;            /* OUT: Device IO flags */
  120. {
  121.     int useFlags;
  122.  
  123.     /*
  124.      * Because there can only be a single reader of dev syslog,
  125.      * and it is most always a local process, we deny a reopen
  126.      * for reading.  Unfortuneatly we can't always tell exactly
  127.      * because 'refs' includes writers.  The whole usage state
  128.      * needs to be fixed to be 'readers', not 'refs'.
  129.      */
  130.     if (refs == writers) {
  131.     useFlags = FS_WRITE;
  132.     } else {
  133.     return(DEV_BUSY);
  134.     }
  135.     return( Dev_SyslogOpen(devicePtr, useFlags, token, (int *) NIL) );
  136. }
  137.  
  138.  
  139. /*
  140.  *----------------------------------------------------------------------
  141.  *
  142.  * Dev_SyslogRead --
  143.  *
  144.  *    Copy data out of the syslog buffer.
  145.  *
  146.  * Results:
  147.  *    FS_WOULD_BLOCK if no data available, otherwise SUCCESS.
  148.  *
  149.  * Side effects:
  150.  *    Data is removed from the syslog buffer.
  151.  *
  152.  *----------------------------------------------------------------------
  153.  */
  154. /*ARGSUSED*/
  155. ReturnStatus
  156. Dev_SyslogRead(devicePtr, readPtr, replyPtr)
  157.     Fs_Device    *devicePtr;
  158.     Fs_IOParam    *readPtr;    /* Read parameter block */
  159.     Fs_IOReply    *replyPtr;    /* Return length and signal */ 
  160. {
  161.     int        toRead;
  162.     int        bytesLeft;
  163.     Address    copyAddr;
  164.     Address    bufPtr = readPtr->buffer;
  165.  
  166.     bytesLeft = readPtr->length;
  167.  
  168.     MASTER_LOCK(&syslogMutex);
  169.     overflow = FALSE;
  170.     if (firstIndex == -1) {
  171.     replyPtr->length = 0;
  172.     MASTER_UNLOCK(&syslogMutex);
  173.     return(FS_WOULD_BLOCK);
  174.     }
  175.     if (firstIndex > lastIndex) {
  176.     toRead = SYSLOG_BUF_SIZE - firstIndex;
  177.     copyAddr = &syslogBuffer[firstIndex];
  178.     if (toRead <= bytesLeft) {
  179.         firstIndex = 0;
  180.     } else {
  181.         toRead = bytesLeft;
  182.         firstIndex += toRead;
  183.     }
  184.     bcopy(copyAddr, bufPtr,toRead);
  185.     bufPtr += toRead;
  186.     bytesLeft -= toRead;
  187.     }
  188.     if (bytesLeft > 0) {
  189.     toRead = lastIndex - firstIndex + 1;
  190.     copyAddr = &syslogBuffer[firstIndex];
  191.     if (toRead <= bytesLeft) {
  192.         firstIndex = -1;
  193.         lastIndex = -1;
  194.     } else {
  195.         toRead = bytesLeft;
  196.         firstIndex += toRead;
  197.     }
  198.     bcopy(copyAddr, bufPtr,toRead);
  199.     bytesLeft -= toRead;
  200.     }
  201.     MASTER_UNLOCK(&syslogMutex);
  202.     replyPtr->length = readPtr->length - bytesLeft;
  203.     return(SUCCESS);
  204. }
  205.  
  206.  
  207. /*
  208.  *----------------------------------------------------------------------
  209.  *
  210.  * Dev_SyslogWrite --
  211.  *
  212.  *    Write characters to the system log.  If the device isn't open
  213.  *    then Mach_MonPutChar is used to output directly to the screen.  
  214.  *    Otherwise data is output to a buffer that is emptied by
  215.  *    reading the syslog device.
  216.  *
  217.  * Results:
  218.  *    SUCCESS.
  219.  *
  220.  * Side effects:
  221.  *    Data is written to the console or to the buffer.
  222.  *
  223.  *----------------------------------------------------------------------
  224.  */
  225. /*ARGSUSED*/
  226. ReturnStatus
  227. Dev_SyslogWrite(devicePtr, writePtr, replyPtr)
  228.     Fs_Device     *devicePtr;        /* Ignored. */
  229.     Fs_IOParam    *writePtr;    /* Standard write parameter block */
  230.     Fs_IOReply    *replyPtr;    /* Return length and signal */
  231. {
  232.     int    i;
  233.     int    toWrite;
  234.     int origSize = writePtr->length;
  235.     Address bufPtr = writePtr->buffer;
  236.  
  237.  
  238.     if (!syslogEnable) {
  239.     replyPtr->length = writePtr->length;
  240.     return(SUCCESS);
  241.     }
  242.  
  243.     if (!dbg_UsingSyslog) {
  244.     if (!openForReading) {
  245.         for (i = 0; i < writePtr->length; i++, bufPtr++) {
  246.         Mach_MonPutChar(*bufPtr);
  247.         }
  248.         replyPtr->length = writePtr->length;
  249.         return(SUCCESS);
  250.     }
  251.     MASTER_LOCK(&syslogMutex);
  252.     }
  253.  
  254.     if (firstIndex != -1 && firstIndex <= lastIndex) {
  255.     /*
  256.      * Fill up until the end of the buffer or until run out of
  257.      * bytes, whichever comes first.
  258.      */
  259.     toWrite = SYSLOG_BUF_SIZE - (lastIndex + 1);
  260.     if (toWrite > writePtr->length) {
  261.         toWrite = writePtr->length;
  262.     }
  263.     bcopy(bufPtr, &syslogBuffer[lastIndex + 1], toWrite);
  264.     writePtr->length -= toWrite;
  265.     bufPtr += toWrite;
  266.     lastIndex += toWrite;
  267.     }
  268.     if (writePtr->length > 0) {
  269.     int    nextIndex;
  270.  
  271.     nextIndex = lastIndex + 1;
  272.     if (nextIndex == SYSLOG_BUF_SIZE) {
  273.         nextIndex = 0;
  274.     }
  275.     if (nextIndex == firstIndex) {
  276.         /*
  277.          * Buffer overflow
  278.          */
  279.         if (!overflow) {
  280.         Mach_MonPrintf("Dev_SyslogWrite: Buffer overflow ...\n");
  281.         overflow = TRUE;
  282.         }
  283.         for (i = 0; i < writePtr->length; i++, bufPtr++) {
  284.         Mach_MonPutChar(*bufPtr);
  285.         }
  286.         /*
  287.          * Make sure we return that the entire amount was written.
  288.          */
  289.         writePtr->length = 0;
  290.     } else {
  291.         if (firstIndex == -1) {
  292.         toWrite = SYSLOG_BUF_SIZE;
  293.         firstIndex = 0;
  294.         } else {
  295.         toWrite = firstIndex - nextIndex;
  296.         }
  297.         if (toWrite > writePtr->length) {
  298.         toWrite = writePtr->length;
  299.         }
  300.         bcopy(bufPtr, syslogBuffer, toWrite);
  301.         lastIndex = nextIndex + toWrite - 1;
  302.         writePtr->length -= toWrite;
  303.     }
  304.     }
  305.     if (!dbg_UsingSyslog) {
  306.     Fsio_DevNotifyReader(notifyToken);
  307.     MASTER_UNLOCK(&syslogMutex);
  308.     }
  309.     replyPtr->length = origSize - writePtr->length;
  310.     return(SUCCESS);
  311. }
  312.  
  313.  
  314.  
  315. /*
  316.  *----------------------------------------------------------------------
  317.  *
  318.  * Dev_SyslogPutChar --
  319.  *
  320.  *    Write a single character to the system log.
  321.  *
  322.  * Results:
  323.  *    None.
  324.  *
  325.  * Side effects:
  326.  *    None.
  327.  *
  328.  *----------------------------------------------------------------------
  329.  */
  330. /*ARGSUSED*/
  331. void
  332. Dev_SyslogPutChar(ch)
  333.     char    ch;
  334. {
  335.     Fs_IOParam io;
  336.     Fs_IOReply reply;
  337.  
  338.     io.buffer = &ch;
  339.     io.length = 1;
  340.     io.offset = 0;
  341.     io.flags = 0;
  342.     reply.signal = 0;
  343.  
  344.     (void) Dev_SyslogWrite((Fs_Device *) NIL, &io, &reply);
  345. }
  346.  
  347.  
  348. /*
  349.  *----------------------------------------------------------------------
  350.  *
  351.  * Dev_SyslogClose --
  352.  *
  353.  *    Close the system log and flush any remaining output.
  354.  *
  355.  * Results:
  356.  *    SUCCESS        - always returned.
  357.  *
  358.  * Side effects:
  359.  *    The console is "closed".
  360.  *
  361.  *----------------------------------------------------------------------
  362.  */
  363. /* ARGSUSED */
  364. ReturnStatus
  365. Dev_SyslogClose(devicePtr, useFlags, openCount, writerCount)
  366.     Fs_Device    *devicePtr;
  367.     int        useFlags;
  368.     int        openCount;
  369.     int        writerCount;
  370. {
  371.     int    i;
  372.  
  373.     MASTER_LOCK(&syslogMutex);
  374.     if (useFlags & FS_READ) {
  375.     openForReading = FALSE;
  376.     if (firstIndex != -1) {
  377.         if (firstIndex <= lastIndex) {
  378.         for (i = firstIndex; i <= lastIndex; i++) {
  379.             Mach_MonPutChar(syslogBuffer[i]);
  380.         }
  381.         } else {
  382.         for (i = firstIndex; i < SYSLOG_BUF_SIZE; i++) {
  383.             Mach_MonPutChar(syslogBuffer[i]);
  384.         }
  385.         for (i = 0; i <= lastIndex; i++)  {
  386.             Mach_MonPutChar(syslogBuffer[i]);
  387.         }
  388.         }
  389.         firstIndex = -1;
  390.         lastIndex = -1;
  391.     }
  392.     }
  393.     MASTER_UNLOCK(&syslogMutex);
  394.     return(SUCCESS);
  395. }
  396.  
  397.  
  398. /*
  399.  *----------------------------------------------------------------------
  400.  *
  401.  * Dev_SyslogIOControl --
  402.  *
  403.  *    Perform device-specific functions with the console.
  404.  *
  405.  * Results:
  406.  *    GEN_NOT_IMPLEMENTED if io control not supported.
  407.  *
  408.  * Side effects:
  409.  *    None.
  410.  *
  411.  *----------------------------------------------------------------------
  412.  */
  413. /* ARGSUSED */
  414. ReturnStatus
  415. Dev_SyslogIOControl(devicePtr, ioctlPtr, replyPtr)
  416.     Fs_Device            *devicePtr;
  417.     Fs_IOCParam        *ioctlPtr;
  418.     Fs_IOReply        *replyPtr;
  419. {
  420.     ReturnStatus    status = SUCCESS;
  421.  
  422.     MASTER_LOCK(&syslogMutex);
  423.     switch (ioctlPtr->command) {
  424.     case    IOC_REPOSITION:
  425.         /*
  426.          * Reposition doesn't matter
  427.          */
  428.         break;
  429.     case    IOC_GET_FLAGS:
  430.     case    IOC_SET_FLAGS:
  431.     case    IOC_SET_BITS:
  432.     case    IOC_CLEAR_BITS:
  433.         /*
  434.          * No syslog specific bits are set this way.
  435.          */
  436.         break;
  437. #ifdef notdef
  438.     case    IOC_TRUNCATE:
  439.         firstIndex = -1;
  440.         lastIndex = - 1;
  441.         break;
  442. #endif
  443.  
  444.     default:
  445.         status = GEN_NOT_IMPLEMENTED;
  446.     }
  447.     MASTER_UNLOCK(&syslogMutex);
  448.     return(status);
  449. }
  450.  
  451.  
  452. /*
  453.  *----------------------------------------------------------------------
  454.  *
  455.  * Dev_SyslogSelect --
  456.  *
  457.  *    Perform device-specific select functions with the console.
  458.  *
  459.  * Results:
  460.  *    SUCCESS    
  461.  *
  462.  * Side effects:
  463.  *    None.
  464.  *
  465.  *----------------------------------------------------------------------
  466.  */
  467. /*ARGSUSED*/
  468. ReturnStatus
  469. Dev_SyslogSelect(devicePtr, readPtr, writePtr, exceptPtr)
  470.     Fs_Device            *devicePtr;
  471.     int            *readPtr;
  472.     int            *writePtr;
  473.     int            *exceptPtr;
  474. {
  475.     MASTER_LOCK(&syslogMutex);
  476.     if (*readPtr) {
  477.     if (lastIndex == -1) {
  478.         *readPtr = 0;
  479.     }
  480.     }
  481.     if (*writePtr) {
  482.     if (firstIndex == lastIndex + 1) {
  483.         *writePtr = 0;
  484.     }
  485.     }
  486.     *exceptPtr = 0;
  487.     MASTER_UNLOCK(&syslogMutex);
  488.     return(SUCCESS);
  489. }
  490.  
  491. static    Boolean    savedOpenForReading;
  492. static    int    syslogDebugCount = 0;
  493.  
  494.  
  495. /*
  496.  *----------------------------------------------------------------------
  497.  *
  498.  * Dev_SyslogDebug --
  499.  *
  500.  *    Start or stop redirecting output to the log buffer.  This is intended
  501.  *    to be called by Dbg_Main when entering and leaving the debugger and
  502.  *    by panic() so that debugger output will go on the
  503.  *    console since no process can run to flush the buffer.
  504.  *
  505.  * Results:
  506.  *    None.
  507.  *
  508.  * Side effects:
  509.  *    Redirecting output to the log buffer is turned off or on.
  510.  *
  511.  *----------------------------------------------------------------------
  512.  */
  513. void
  514. Dev_SyslogDebug(stopLog)
  515.     Boolean    stopLog;    /* TRUE => stop storing log output into the
  516.                  *         buffer. */
  517. {
  518.     if (stopLog) {
  519.     if (syslogDebugCount == 0) {
  520.         savedOpenForReading = openForReading;
  521.         openForReading = FALSE;
  522.     }
  523.     syslogDebugCount++;
  524.     } else {
  525.     syslogDebugCount--;
  526.     if (syslogDebugCount == 0) {
  527.         openForReading = savedOpenForReading;
  528.     }
  529.     }
  530. }
  531.  
  532.  
  533.  
  534. /*
  535.  *----------------------------------------------------------------------
  536.  *
  537.  * Dev_SyslogReturnBuffer --
  538.  *
  539.  *    Return the data in the syslog buffer to the caller.  Intended to be
  540.  *    called by the debugger.
  541.  *
  542.  * Results:
  543.  *    Pointer to buffer and the first and last indices.
  544.  *
  545.  * Side effects:
  546.  *    None.
  547.  *
  548.  *----------------------------------------------------------------------
  549.  */
  550. void
  551. Dev_SyslogReturnBuffer(bufPtrPtr, firstIndexPtrPtr, lastIndexPtrPtr, bufSizePtr)
  552.     char    **bufPtrPtr;
  553.     int        **firstIndexPtrPtr;
  554.     int        **lastIndexPtrPtr;
  555.     int        *bufSizePtr;
  556. {
  557.     *bufPtrPtr = syslogBuffer;
  558.     *firstIndexPtrPtr = &firstIndex;
  559.     *lastIndexPtrPtr = &lastIndex;
  560.     *bufSizePtr = SYSLOG_BUF_SIZE;
  561. }
  562.  
  563.  
  564. /*
  565.  *----------------------------------------------------------------------
  566.  *
  567.  * Dev_SyslogDisable --
  568.  *
  569.  *    Toggles syslog on/off.
  570.  *
  571.  * Results:
  572.  *    None.
  573.  *
  574.  * Side effects:
  575.  *    None.
  576.  *
  577.  *----------------------------------------------------------------------
  578.  */
  579. /* ARGSUSED */
  580. void
  581. Dev_SyslogDisable(dummy)
  582.     ClientData dummy;
  583. {
  584.     if (syslogEnable) {
  585.     MASTER_LOCK(&syslogMutex);
  586.     firstIndex = -1;
  587.     lastIndex = - 1;
  588.     syslogEnable = FALSE;
  589.     MASTER_UNLOCK(&syslogMutex);
  590.     } else {
  591.     MASTER_LOCK(&syslogMutex);
  592.     syslogEnable = TRUE;
  593.     MASTER_UNLOCK(&syslogMutex);
  594.     }
  595. }
  596.